home *** CD-ROM | disk | FTP | other *** search
- /*
- //
- // Copyright (C) 1991 Texas Instruments Incorporated.
- //
- // Permission is granted to any individual or institution to use, copy, modify,
- // and distribute this software, provided that this complete copyright and
- // permission notice is maintained, intact, in all copies and supporting
- // documentation.
- //
- // Texas Instruments Incorporated provides this software "as is" without
- // express or implied warranty.
- //
- * $XConsortium: main.c,v 1.33 89/07/21 11:35:21 jim Exp $
- */
- #include "def.h"
- #ifdef hpux
- #define sigvec sigvector
- #endif /* hpux */
-
- #include <signal.h>
- #include <errno.h>
- #ifdef VMS
- #include <unixio.h>
- #endif
-
- #ifdef DEBUG
- int debug;
- #endif
-
- /**
- ** MODIFIED: 06/25/90 by MBN
- **
- ** Added the -X option to generate dependencies for a file but *not* an RCS
- ** dependency. This is useful for LEX and YACC generated files that have
- ** include statements, but whose source is machine-produced.
- **/
-
- /**
- ** MODIFIED: 06/13/90 by MBN
- **
- ** Modified basename() function to check extensions and added SourceExtensions
- ** array of valid source filename extensions.
- **/
-
- /**
- ** MODIFIED: 06/08/90 by MBN
- **
- ** Add a dependency to automatically link each header file when checkout
- ** out to the project include directory if the command line option -L
- ** is specified
- **/
-
- /**
- ** MODIFIED: 05/16/90 by MBN
- **
- ** Add a dependency for each file in the file list on the command line to
- ** its RCS master of the form "foo.h :: $(RCSDIR)foo.h$(RCSEXT)" if the
- ** command line option -R (for RCS) is specified
- **/
-
- /**
- ** MODIFIED: 05/14/90 by MBN
- **
- ** If the extension on a file is .l, .y, .h, .c, or .C don't zap it! This
- ** allows mkdepend to calculate dependencies for files contained in the SRCS
- ** list in the Imake file. If this is not done, then "foo.h" becomes "foo.o"
- **/
-
- /**
- ** MODIFIED: 05/11/90 by MBN
- **
- ** Removed hard-coded path separator character and changed to a user-defined
- ** character constant. The symbol PATHSEP defaults to '/' but can be over
- ** ridden on the command line to mkdepend.
- **/
-
- char path_sep = PATHSEP;
- /* The following is used to find the end of the directory information. In
- UNIX, it is '/'; in VMS, however, it is ']', which differs from the path
- separator '.'.
- */
- char path_end = PATHSEP;
-
- char *ProgramName;
-
- char *directives[] = {
- "if",
- "ifdef",
- "ifndef",
- "else",
- "endif",
- "define",
- "undef",
- "include",
- "line",
- "pragma",
- "error",
- "ident",
- "sccs",
- "elif",
- "eject",
- NULL
- };
-
- /**
- ** SourceExtensions contains the extensions for files that have conversion
- ** rules, that is, get transposed from one type of "thing" to another. Any
- ** file passed on the command line that does *NOT* have one of these extensions
- ** is assumed to be a miscellaneous file and, if the -R (RCS Checkout) flag
- ** is provided, will result in a dependency added for to check out the file
- ** from under RCS control.
- **/
-
- char *SourceExtensions[] = {
- "h",
- "hxx",
- "c",
- "cxx",
- "C",
- "y",
- "Y",
- "l",
- "L",
- NULL
- };
-
- struct symtab predefs[] = {
- #ifdef apollo
- {"apollo", NULL},
- #endif
- #ifdef ibm032
- {"ibm032", NULL},
- #endif
- #ifdef sun
- {"sun", NULL},
- #endif
- #ifdef os2
- {"os2", NULL},
- #endif
- #ifdef DOS
- {"DOS", NULL},
- #endif
- #ifdef hpux
- {"hpux", NULL},
- #endif
- #ifdef vax
- {"vax", NULL},
- #endif
- #ifdef VMS
- {"VMS", NULL},
- #endif
- #ifdef cray
- {"cray", NULL},
- #endif
- #ifdef CRAY
- {"CRAY", NULL},
- #endif
- #ifdef att
- {"att", NULL},
- #endif
- #ifdef mips
- {"mips", NULL},
- #endif
- #ifdef ultrix
- {"ultrix", NULL},
- #endif
- #ifdef mc68000
- {"mc68000", NULL},
- #endif
- #ifdef mc68020
- {"mc68020", NULL},
- #endif
- #ifdef __GNUC__
- {"__GNUC__", NULL},
- #endif
- #ifdef __STDC__
- {"__STDC__", NULL},
- #endif
- {NULL, NULL}
- };
-
- struct symtab deflist[ MAXDEFINES ];
- struct inclist inclist[ MAXFILES ],
- *inclistp = inclist;
-
- char *filelist[ MAXFILES ];
- char *dependonlylist[ MAXFILES ];
- char *includedirs[ MAXDIRS ];
- char *notdotdot[ MAXDIRS ];
- char *objfile = ".o";
- char *startat = "# DO NOT DELETE THIS LINE -- mkdepend depends on it.";
- int width = 78;
- boolean printed = FALSE;
- boolean verbose = FALSE;
- boolean show_where_not = FALSE;
- boolean rcs_dependency = FALSE;
- boolean link_dependency = FALSE;
-
- void redirect();
-
- static
- #ifdef SIGNALRETURNSINT
- int
- #else
- void
- #endif
- catch (sig)
- int sig;
- {
- fflush (stdout);
- log_fatal ("got signal %d\n", sig);
- }
-
- #ifndef os2
- #ifndef USG
- struct sigvec sig_vec = {
- catch,
- (1<<(SIGINT -1))
- |(1<<(SIGQUIT-1))
- |(1<<(SIGBUS-1))
- |(1<<(SIGILL-1))
- |(1<<(SIGSEGV-1))
- |(1<<(SIGHUP-1))
- |(1<<(SIGPIPE-1))
- |(1<<(SIGSYS-1)),
- 0
- };
- #endif /* USG */
- #endif /* os2 */
-
- main(argc, argv)
- int argc;
- char **argv;
- {
- register struct symtab *symp = deflist;
- register char **fp = filelist;
- register char **incp = includedirs;
- register char **temp;
- register char **dp = dependonlylist;
- register char *p;
- register struct inclist *ip;
- char *makefile = NULL;
- struct filepointer *filecontent;
- struct symtab *psymp = predefs;
- char *endmarker = NULL;
- char buf[ 2 ];
-
- ProgramName = argv[0];
-
- while (psymp->s_name)
- *symp++ = *psymp++;
- for(argc--, argv++; argc; argc--, argv++) {
- /* if looking for endmarker then check before parsing */
- if (endmarker && strcmp (endmarker, *argv) == 0) {
- endmarker = NULL;
- continue;
- }
- if (**argv != '-') {
- /* scan existing filenames and only add to list if
- this new one has not already been specified */
- for (temp = filelist; *temp; temp++)
- if(strcmp(argv[0],*temp) == 0)
- break;
- if (*temp == NULL)
- *fp++ = argv[0];
- continue;
- }
- switch(argv[0][1]) {
- case '-':
- endmarker = &argv[0][2];
- if (endmarker[0] == '\0') endmarker = "--";
- break;
- case 'D':
- symp->s_name = argv[0]+2;
- if (*symp->s_name == '\0') {
- symp->s_name = *(++argv);
- argc--;
- }
- for (p=symp->s_name; *p ; p++)
- if (*p == '=') {
- *p++ = '\0';
- break;
- }
- symp->s_value = p;
- symp++;
- break;
- case 'R':
- rcs_dependency = TRUE;
- break;
- case 'L':
- link_dependency = TRUE;
- break;
- case 'X':
- if(argv[0][2] != ' ' && argv[0][2] != '\0')
- {
- *dp++ = &(argv[0][2]);
- *fp++ = &(argv[0][2]);
- }
- break;
- case 'I':
- *incp++ = argv[0]+2;
- if (**(incp-1) == '\0') {
- *(incp-1) = *(++argv);
- argc--;
- }
- break;
- /* do not use if endmarker processing */
- case 'w':
- if (endmarker) break;
- if (argv[0][2] == '\0') {
- argv++;
- argc--;
- width = atoi(argv[0]);
- } else
- width = atoi(argv[0]+2);
- break;
- case 'o':
- if (endmarker) break;
- if (argv[0][2] == '\0') {
- argv++;
- argc--;
- objfile = argv[0];
- } else
- objfile = argv[0]+2;
- break;
- case 'v':
- if (endmarker) break;
- verbose = TRUE;
- #ifdef DEBUG
- if (argv[0][2])
- debug = atoi(argv[0]+2);
- #endif
- break;
- case 's':
- if (endmarker) break;
- startat = argv[0]+2;
- if (*startat == '\0') {
- startat = *(++argv);
- argc--;
- }
- if (*startat != '#')
- log_fatal("-s flag's value should start %s\n",
- "with '#'.");
- break;
- case 'f':
- if (endmarker) break;
- makefile = argv[0]+2;
- if (*makefile == '\0') {
- makefile = *(++argv);
- argc--;
- }
- break;
-
- case 'P': /* User-specified path separator character */
- if( argv[0][2] == '\0' || argv[0][2] == ' ')
- log_fatal("invalid pathname separator specified\n");
- path_sep = argv[0][2];
- break;
-
- case 'Q': /* User-specified path end character */
- path_end = argv[0][2];
- break;
-
- /* Ignore -O, -g so we can just pass ${CFLAGS} to
- makedepend
- */
- case 'O':
- case 'g':
- break;
- default:
- if (endmarker) break;
- /* log_fatal("unknown opt = %s\n", argv[0]); */
- do_log("ignoring option %s\n", argv[0]);
- }
- }
-
- redirect(startat, makefile);
-
- /*
- * catch signals.
- */
- #ifdef USG
- /* should really reset SIGINT to SIG_IGN if it was. */
- signal (SIGHUP, catch);
- signal (SIGINT, catch);
- signal (SIGQUIT, catch);
- signal (SIGILL, catch);
- signal (SIGBUS, catch);
- signal (SIGSEGV, catch);
- signal (SIGSYS, catch);
- #else
- #ifndef os2
- sigvec(SIGHUP, &sig_vec, (struct sigvec *)0);
- sigvec(SIGINT, &sig_vec, (struct sigvec *)0);
- sigvec(SIGQUIT, &sig_vec, (struct sigvec *)0);
- sigvec(SIGILL, &sig_vec, (struct sigvec *)0);
- sigvec(SIGBUS, &sig_vec, (struct sigvec *)0);
- sigvec(SIGSEGV, &sig_vec, (struct sigvec *)0);
- sigvec(SIGSYS, &sig_vec, (struct sigvec *)0);
- #endif
- #endif
-
- /*
- * now peruse through the list of files.
- */
- for(fp=filelist; *fp; fp++) {
- if(is_source_file(*fp)) {
- filecontent = getfile(*fp);
- ip = newinclude(*fp, (char *)NULL);
- find_includes(filecontent, ip, ip, 0);
- freefile(filecontent);
- recursive_pr_include(ip, ip->i_file, *fp);
- }
-
- if(is_depend_only_file(*fp) == TRUE) {
- sprintf(buf, "\n");
- fwrite(buf, strlen(buf), 1, stdout);
- }
- else if(rcs_dependency == TRUE) {
- rcs_pr(*fp, "$(RCSDIR)", "$(RCSEXT)");
- if (link_dependency == TRUE)
- link_pr(*fp);
- }
- inc_clean();
- }
- if (printed)
- printf("\n");
- exit(0);
- }
-
- int is_source_file(file)
- register char *file;
- {
- register char *p, **q;
-
- for (p=file+strlen(file); p>file && *p != path_sep; p--) ;
-
- if (*p == path_sep)
- p++;
-
- file = copy(p);
- for(p=file+strlen(file); p>file && *p != '.'; p--) ;
-
- if (*p == '.')
- {
- for( q = SourceExtensions; *q; q++)
- if( !strcmp(*q, (p+1)) )
- {
- return 1;
- }
- }
- return 0;
- }
-
- int is_depend_only_file(file)
- register char *file;
- {
- register char *p, **q;
-
- for (p=file+strlen(file); p>file && *p != path_sep; p--) ;
-
- if (*p == path_sep)
- p++;
-
- for( q = dependonlylist; *q; q++)
- if( !strcmp(*q, p) )
- return 1;
- return 0;
- }
-
- struct filepointer *getfile(file)
- char *file;
- {
- register int i;
- struct filepointer *content;
- struct stat st;
- FILE *fd;
-
- content = (struct filepointer *)malloc(sizeof(struct filepointer));
- if ((fd = fopen(file, "r")) == NULL) {
- do_log("cannot open \"%s\" [errno=%d]\n", file, errno);
- content->f_p = content->f_base = content->f_end = malloc(1);
- *content->f_p = '\0';
- return(content);
- }
- stat(file, &st);
- content->f_len = st.st_size+1;
- content->f_base = malloc(content->f_len);
- if (content->f_base == NULL)
- log_fatal("cannot allocate mem\n");
- for (i = 0; i < st.st_size; ++i)
- content->f_base[i] = getc (fd);
- fclose(fd);
- content->f_p = content->f_base;
- content->f_end = content->f_base + st.st_size;
- *content->f_end = '\0';
- content->f_line = 0;
- return(content);
- }
-
- freefile(fp)
- struct filepointer *fp;
- {
- free(fp->f_base);
- free(fp);
- }
-
- /*VARARGS*/
- log_fatal(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
- char* x0;
- {
- do_log(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
- exit (1);
- }
-
- /*VARARGS0*/
- do_log(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9)
- char* x0;
- {
- fprintf(stderr, "%s: ", ProgramName);
- fprintf(stderr, x0,x1,x2,x3,x4,x5,x6,x7,x8,x9);
- }
-
- char *copy(str)
- register char *str;
- {
- register char *p = malloc(strlen(str) + 1);
-
- strcpy(p, str);
- return(p);
- }
-
- match(str, list)
- register char *str, **list;
- {
- register int i;
-
- for (i=0; *list; i++, list++)
- if (strcmp(str, *list) == 0)
- return(i);
- return(-1);
- }
-
- /*
- * Get the next line. We only return lines beginning with '#' since that
- * is all this program is ever interested in.
- */
- char *getline(filep)
- register struct filepointer *filep;
- {
- register char *p, /* walking pointer */
- *eof, /* end of file pointer */
- *bol; /* beginning of line pointer */
- register lineno; /* line number */
-
- p = filep->f_p;
- eof = filep->f_end;
- if (p >= eof)
- return((char *)NULL);
- lineno = filep->f_line;
-
- for(bol = p--; ++p < eof; ) {
- if (*p == '/' && *(p+1) == '*') { /* consume comments */
- *p++ = ' ', *p++ = ' ';
- while (*p) {
- if (*p == '*' && *(p+1) == '/') {
- *p++ = ' ', *p = ' ';
- break;
- }
- else if (*p == '\n')
- lineno++;
- *p++ = ' ';
- }
- continue;
- }
- if (*p == '/' && *(p+1) == '/') { /* consume EOL comments */
- *p++ = ' ', *p++ = ' ';
- while (*p != '\n') { *p++ = ' '; }
- }
- if (*p == '\n') {
- lineno++;
- if (*bol == '#') {
- register char *cp;
-
- *p++ = '\0';
- /* punt lines with just # (yacc generated) */
- for (cp = bol+1;
- *cp && (*cp == ' ' || *cp == '\t'); cp++);
- if (*cp) goto done;
- }
- bol = p+1;
- }
- }
- if (*bol != '#')
- bol = NULL;
- done:
- filep->f_p = p;
- filep->f_line = lineno;
- return(bol);
- }
-
- #ifdef VMS
- void unlink (name)
- char *name;
- {
- char command[200];
- /* Use the DELETE command (executed through SYSTEM), since VMS does not
- support UNLINK */
- sprintf (command, "delete %s;", name);
- system (command);
- }
- #endif
-
- #ifdef USG
- int rename (from, to)
- char *from, *to;
- {
- (void) unlink (to);
- if (link (from, to) == 0) {
- unlink (from);
- return 0;
- } else {
- return -1;
- }
- }
- #endif /* USG */
-
- void
- redirect(line, makefile)
- char *line,
- *makefile;
- {
- struct stat st;
- FILE *fdin, *fdout;
- char backup[ BUFSIZ ],
- buf[ BUFSIZ ];
- boolean found = FALSE;
- int len;
-
- /*
- * if makefile is "-" then let it pour onto stdout.
- */
- if (makefile && *makefile == '-' && *(makefile+1) == '\0')
- return;
-
- /*
- * use a default makefile is not specified.
- */
- if (!makefile) {
- if (stat("makefile", &st) == 0)
- makefile = "makefile";
- else if (stat("Makefile", &st) == 0)
- makefile = "Makefile";
- else
- log_fatal("[mM]akefile is not present\n");
- }
- else
- stat(makefile, &st);
- if ((fdin = fopen(makefile, "r")) == NULL)
- log_fatal("cannot open \"%s\"\n", makefile);
- sprintf(backup, "%s.bak", makefile);
- unlink(backup);
- fclose(fdin);
- if (rename(makefile, backup) < 0)
- log_fatal("cannot rename %s to %s\n", makefile, backup);
- fdin = fopen(backup, "r");
- if ((fdout = freopen(makefile, "w", stdout)) == NULL)
- log_fatal("cannot open \"%s\"\n", backup);
- len = strlen(line);
- while (fgets(buf, BUFSIZ, fdin) && !found) {
- if (*buf == '#' && strncmp(line, buf, len) == 0)
- found = TRUE;
- fputs(buf, fdout);
- }
- if (!found) {
- if (verbose)
- do_log("Adding new delimiting line \"%s\" and dependencies...\n",
- line);
- puts(line); /* same as fputs(fdout); but with newline */
- }
- fflush(fdout);
- #ifdef USG
- chmod(makefile, st.st_mode);
- #else
- /* fchmod(fileno(fdout), st.st_mode); */
- chmod(makefile, st.st_mode);
- #endif /* USG */
- }
-